/**
 * 
 */
package com.novartis.nims.imagedc.application;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.swing.table.AbstractTableModel;

import com.novartis.nims.imagedc.logic.AttributeTagDelegate;
import com.novartis.nims.imagedc.logic.Scan;

/**
 * @author snydejo2
 *
 */
public class ScanTableModel extends AbstractTableModel {

	/**
	 * 
	 */
	private static final long serialVersionUID = 6633349591510998560L;
	private List<Scan> scanList;
	private List<Boolean> selectionList;
	
	private static final AttributeTagDelegate MODALITY_TAG = new AttributeTagDelegate("0008", "0060");
	private static final AttributeTagDelegate SERIES_DESC_TAG = new AttributeTagDelegate("0008", "103E");
	private static final AttributeTagDelegate ACQUISITION_DATE_TAG = new AttributeTagDelegate("0008", "0022");
	private static final AttributeTagDelegate ACQUISITION_TIME_TAG = new AttributeTagDelegate("0008", "0032");
	private static final AttributeTagDelegate PATIENT_NAME_TAG = new AttributeTagDelegate("0010", "0010");
	private static final AttributeTagDelegate PATIENT_ID_TAG = new AttributeTagDelegate("0010", "0020");
	
	static enum EditState {
		FIXED, REQUIRED, OPTIONAL;
	}
	
	static enum Column {
		SUBMIT("Submit", EditState.OPTIONAL),
		PATIENT_NAME("Patient Name", EditState.FIXED),
		PATIENT_ID("Patient ID", EditState.FIXED),
		MODALITY("Modality", EditState.FIXED),
		SERIES_DESCRIPTION("Series Description", EditState.FIXED),
		ACQUISITION_DATE("Acquisition Date", EditState.FIXED),
		ACQUISITION_TIME("Acquisition Time", EditState.FIXED),
//		SCAN_KEY("Scan Key", EditState.FIXED),
//		SCAN_REPEAT_NUMBER("Scan Repeat Number", EditState.FIXED),
		STUDY_ID("Study ID", EditState.REQUIRED),
		SITE_SUBJECT_ID("Site_Subject ID", EditState.REQUIRED),
		VISIT_NAME("Visit Name", EditState.REQUIRED),
		VISIT_NUMBER("Visit Number", EditState.OPTIONAL),
		VISIT_REPEAT_NUMBER("Visit Repeat Number", EditState.OPTIONAL),
		SCAN_NAME("Scan Name", EditState.REQUIRED);
		
		private final String columnName;
		private final EditState editState;
		
		private Column(String theColumnName, EditState theEditState) {
			columnName = theColumnName;
			editState = theEditState;
		}
		
		String getColumnName() {
			return columnName;
		}
		
		EditState getEditState() {
			return editState;
		}
	}

	/**
	 * 
	 */
	public ScanTableModel(Collection<Scan> scans, Collection<Boolean> selections) {
		scanList = new ArrayList<Scan>(scans);
		selectionList = new ArrayList<Boolean>(selections);
	}

	/* (non-Javadoc)
	 * @see javax.swing.table.TableModel#getColumnCount()
	 */
	public int getColumnCount() {
		return Column.values().length;
	}

	/* (non-Javadoc)
	 * @see javax.swing.table.TableModel#getRowCount()
	 */
	public int getRowCount() {
		return scanList.size();
	}

	/* (non-Javadoc)
	 * @see javax.swing.table.TableModel#getValueAt(int, int)
	 */
	public Object getValueAt(int rowIndex, int colIndex) {
		Scan scan = scanList.get(rowIndex);
		
		Object value = null;
		
		switch (Column.values()[colIndex]) {
			case SUBMIT: value = selectionList.get(rowIndex); break;
//			case SCAN_KEY: value = scan.getScanKey(); break;
			case SCAN_NAME: value = scan.getScanName(); break;
//			case SCAN_REPEAT_NUMBER: value = scan.getScanRepeatNumber(); break;
			case STUDY_ID: value = scan.getStudyId(); break;
			case SITE_SUBJECT_ID: value = scan.getSiteSubjectId(); break;
			case VISIT_NUMBER: value = scan.getVisitNumber(); break;
			case VISIT_REPEAT_NUMBER: value = scan.getVisitRepeatNumber(); break;
			case VISIT_NAME: value = scan.getVisitName(); break;
			case MODALITY: value = scan.getAttributeValue(MODALITY_TAG); break;
			case SERIES_DESCRIPTION: value = scan.getAttributeValue(SERIES_DESC_TAG); break;
			case ACQUISITION_DATE:
				DateFormat dicomDate = new SimpleDateFormat("yyyyMMdd");
				DateFormat displayDate = new SimpleDateFormat("MMM d, yyyy");
				try {
					value = displayDate.format(dicomDate.parse(scan.getAttributeValue(ACQUISITION_DATE_TAG)));
				} catch (ParseException e) {
					value = scan.getAttributeValue(ACQUISITION_DATE_TAG);
				}
				break;
			case ACQUISITION_TIME:
				DateFormat dicomTime = new SimpleDateFormat("HHmmss");
				DateFormat displayTime = new SimpleDateFormat("h:mm:ss a");
				try {
					value = displayTime.format(dicomTime.parse(scan.getAttributeValue(ACQUISITION_TIME_TAG)));
				} catch (ParseException e) {
					value = scan.getAttributeValue(ACQUISITION_TIME_TAG);
				}
				break;
			case PATIENT_NAME: value = scan.getAttributeValue(PATIENT_NAME_TAG); break;
			case PATIENT_ID: value = scan.getAttributeValue(PATIENT_ID_TAG); break;
		}
		
		return value;
	}

	@Override
	public void setValueAt(Object value, int rowIndex, int colIndex) {
		String stringValue = null;
		
		if (Column.values()[colIndex] == Column.SUBMIT) {
			if (!(value instanceof Boolean)) {
				return;
			}
		} else if (!(value instanceof String)) {
			return;
		} else {
			stringValue = (String)value;
		}
		
		Scan scan = scanList.get(rowIndex);
		
		switch (Column.values()[colIndex]) {
			case SUBMIT: selectionList.set(rowIndex, (Boolean)value); break;
			case SCAN_NAME: scan.setScanName(stringValue); break; 
			case STUDY_ID: scan.setStudyId(stringValue); break;
			case SITE_SUBJECT_ID: scan.setSiteSubjectId(stringValue); break;
			case VISIT_NUMBER: scan.setVisitNumber(stringValue); break;
			case VISIT_REPEAT_NUMBER: scan.setVisitRepeatNumber(stringValue); break;
			case VISIT_NAME: scan.setVisitName(stringValue); break;
		}
	}

	@Override
	public Class<?> getColumnClass(int colIndex) {
		if (colIndex == 0) {
			return Boolean.class;
		} else {
			return String.class;
		}
	}
	
	@Override
	public String getColumnName(int colIndex) {
		return Column.values()[colIndex].getColumnName();
	}

	@Override
	public boolean isCellEditable(int rowIndex, int colIndex) {
		switch (Column.values()[colIndex].getEditState()) {
			case FIXED: return false;
			case REQUIRED: return true;
			case OPTIONAL: return true;
			default: return false;
		}
	}

	public Scan getScanAt(int row) {
		return scanList.get(row);
	}
	
	boolean areRequiredCellsFilled() {
		for (int row = 0; row < getRowCount(); row++) {
			if (selectionList.get(row).equals(Boolean.FALSE)) continue;
			for (int col = 0; col < getColumnCount(); col++) {
				if (Column.values()[col].getEditState() == EditState.REQUIRED) {
					Object value = getValueAt(row, col);
					if (value == null || value.equals("")) {
						return false;
					}
				}
			}
		}
		
		return true;
	}

	public boolean isRowForSubmission(int row) {
		return selectionList.get(row).booleanValue();
	}

}
